package com.opages.netty.demo.netty.rpc.consumer;

import com.opages.netty.demo.netty.rpc.business.BusinessService;
import com.opages.netty.demo.netty.rpc.common.MessageDecoder;
import com.opages.netty.demo.netty.rpc.common.MessageEncoder;
import com.opages.netty.demo.netty.rpc.common.RpcInvoker;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.lang.reflect.Proxy;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

/**
 * @author daizhong.liu
 * @create 2021-12-15 17:16
 **/
public class Consumer {
    private static ConsumerHandler consumerHandler;
    private static ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    public <T> T getBean(Class<T> service) {
        return (T)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                new Class<?>[]{service},
                ((proxy, method, args) -> {
                    if(consumerHandler == null) {
                        register("127.0.0.1", 9998);
                    }
                    RpcInvoker invoker = new RpcInvoker();
                    invoker.setMethod(method);
                    invoker.setParams(args);
                    consumerHandler.setInvoker(invoker);
                return executor.submit(consumerHandler).get();
            }
        ));
    }

    public void register(String ip,int port) {
        EventLoopGroup group = new NioEventLoopGroup();
        consumerHandler = new ConsumerHandler();
        try {
            Bootstrap bootstrap = new Bootstrap()
                    .group(group)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline()
                                    .addLast(new MessageEncoder())
                                    .addLast(new MessageDecoder())
                                    .addLast(consumerHandler);
                        }
                    });
            bootstrap.connect(ip, port).sync();
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Consumer consumer = new Consumer();
        BusinessService businessService = consumer.getBean(BusinessService.class);
        String hello = businessService.hello();
        System.err.println("主程序："+hello);
    }
}
